const { features } = require('process');

module.exports = function (app, api_prefix = '/api/image') {
    const PNGImage = require('pngjs-image'); // 生成png图片
    const Jimp = require('jimp'); // 为图片添加文本
    const path = require("path");
    const fs = require("fs");

    var crypto = require('crypto');
    var md5 = crypto.createHash('md5');
    const log4js = require('log4js');


    const logger = log4js.getLogger();
    log4js.getLogger().debug(`Startup image_generator api_prefix=${api_prefix}`);

    const image_generator_dir = path.join(__dirname, "public/image_generator");
    const icon_dir = path.join(__dirname, "public/icon");
    // cgi, common gateway interface 通用网关接口
    // api, application programming  interface 应用程序接口
    app.use(`${api_prefix}/:purpose`, function (req, res, next) {
        var params = req.method == "GET" ? req.query : req.body;
        var headers = req.headers;
        switch (req.params.purpose) {
            // 获取图片
            case 'get': {
                // 初始化图片参数
                let width = parseInt(params.width || params.w || "128");
                let height = parseInt(params.height || params.h || "128");
                let background_color = params.color || params.c || "0x009050";
                let shape = params.shape || params.s || "rect";
                let feather = parseInt(params.feather || params.feather || "4") || 0;
                let txtColor = params.tcolor || params.tc || "auto";
                // width += 2 * feather;
                // height += 2 * feather;
                // 十六进制特殊处理，如：0xc => 0xcccccc; 0xabc => 0xaabbcc
                if (background_color.indexOf("0x") == 0) {
                    let chars = background_color.slice(2);
                    if (chars.length == 1) {
                        background_color = "0x" + chars.repeat(6);
                    } else if (chars.length == 3) {
                        background_color = "0x";
                        for (let i = 0, len = chars.length; i < len; ++i) {
                            background_color += chars[i].repeat(2);
                        }
                    }
                }
                background_color = parseInt(background_color);
                if (params.random || params.r) {
                    background_color = Math.round(0xffffff * Math.random());
                }
                let text = params.text || params.t || `${width}x${height}`;
                let label = params.label || params.l || ` `;
                // 检查同样配置的文件是否存在临时文件中
                let filename = `${width}x${height}_${shape}_${feather}_${text}_${label}_${txtColor}_${background_color.toString(16)}`;
                filename = getHash(filename);
                filename += ".png";
                let exsisted = false; // 文件是否存在
                try {
                    if (fs.existsSync(path.join(image_generator_dir, filename))) {
                        exsisted = true;
                    }
                } catch(err) {
                    logger.error(err);
                }
                
                var filepath = path.join(image_generator_dir, filename);
                if (!exsisted) {
                    var image = PNGImage.createImage(width, height);
                    // 填充颜色
                    var bgcolor = {
                        red: background_color >> 16 & 0xff,
                        green: background_color >> 8 & 0xff,
                        blue: background_color >> 0 & 0xff,
                        alpha: 0xff
                    };
                    let x = 0, y = 0;
                    switch(shape) {
                        case "circle": {
                            let cx = width >> 1;
                            let cy = height >> 1;
                            let radius = Math.min(width, height) >> 1;
                            let i, iLen = x + width, j, jLen = y + height, index;
                            for (i = x; i < iLen; i++) {
                                for (j = y; j < jLen; j++) {
                                    let alpha = 0;
                                    let dist = Math.sqrt((i - cx) ** 2 + (j - cy) ** 2);
                                    let outoffset = dist + feather - radius;
                                    if (outoffset <= 0) {
                                        alpha = 1;
                                    } else if (outoffset <= feather) {
                                        alpha = 1 - outoffset / feather;
                                    }
                                    if (alpha <= 0) {
                                        continue;
                                    }
                                    bgcolor.alpha = alpha * 0xff;
                                    index = image.getIndex(i, j);
                                    image.setAtIndex(index, bgcolor);
                                }
                            }
                            break;
                        }
                        case "rect":
                        default: {
                            image.fillRect(x, y, width, height, bgcolor);
                            break;
                        }
                    }
                    // 计算亮度值
                    // RGB和YIQ的对应关系用下面的方程式表示：
                    // Y = 0.299R + 0.587G + 0.114B
                    // I = 0.596R - 0.275G - 0.321B
                    // Q = 0.212R - 0.523G + 0.311B
                    var luminance = 0.299 * bgcolor.red + 0.587 * bgcolor.green + 0.114 * bgcolor.blue;

                    var content_font_name;
                    var label_font_name;
                    switch (txtColor) {
                        case "light": {
                            content_font_name = Jimp.FONT_SANS_32_WHITE;
                            label_font_name = Jimp.FONT_SANS_16_WHITE;
                            break;
                        }
                        case "dark": {
                            content_font_name = Jimp.FONT_SANS_32_BLACK;
                            label_font_name = Jimp.FONT_SANS_16_BLACK;
                            break;
                        }
                        case "auto": 
                        default: {
                            content_font_name = Jimp.FONT_SANS_32_WHITE;
                            label_font_name = Jimp.FONT_SANS_16_WHITE;
                            // 如果亮度较高，则使用黑色字体
                            if (luminance / 0xff > 0.5) {
                                content_font_name = Jimp.FONT_SANS_32_BLACK;
                                label_font_name = Jimp.FONT_SANS_16_BLACK;
                            }
                            break;
                        }
                    }
                    
                    
                    // Get low level image object with buffer from the 'imageBuffer' package
                    var imageBuffer = image.getImage();
                    Jimp.loadFont(content_font_name)
                        .then(content_font => {
                            Jimp.loadFont(label_font_name)
                                .then(label_font => {
                                    Jimp.read(imageBuffer)
                                        .then(image => {
                                            image
                                            .print(content_font, 0, 0, {
                                                text: text,
                                                alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
                                                alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE,
                                            }, image.getWidth(), image.getHeight()) // 添加文本
                                            .print(label_font, 0, 0, {
                                                text: label,
                                                alignmentX: Jimp.HORIZONTAL_ALIGN_RIGHT,
                                                alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM,
                                            }, image.getWidth(), image.getHeight())
                                            // .quality(60) // 设置JPEG图片质量
                                            // .greyscale() // 灰度图
                                            .write(filepath, function(err, image) {
                                                if (err) {
                                                    logger.error(err);
                                                } else {
                                                    logger.info(`${filepath} was created`);
                                                    sendFile(req, res, next, filepath);
                                                }
                                            });
                                            return image;
                                        })
                                        .catch(err => {
                                            console.error(err);
                                        });
                                });
                        });
                } else {
                    sendFile(req, res, next, filepath);
                }
                break;
            }
            // 清理缓存
            case 'clean': {
                deleteall(image_generator_dir);
                res.send(result(200, null, `${image_generator_dir} was cleaned`))
                break;
            }
            default:
                res.send(result(404, null, 'Illigel request!'))
                break;
        }
    });

    function deleteall(path) {
        var files = [];
        if(fs.existsSync(path)) {
            files = fs.readdirSync(path);
            files.forEach(function(file, index) {
                var curPath = path + "/" + file;
                if(fs.statSync(curPath).isDirectory()) { // recurse
                    deleteall(curPath);
                } else { // delete file
                    fs.unlinkSync(curPath);
                }
            });
            // fs.rmdirSync(path);
        }
    };

    function getHash(text) {
        var md5 = crypto.createHash('md5');
        return md5.update(text).digest('hex');
    }

    function sendFile(req, res, next, filepath) {
        const options = {
            // root: image_generator_dir,
            dotfiles: 'allow',
            headers: {
                'x-timestamp': Date.now(),
                'x-sent': true
            }
        }
        res.sendFile(filepath, options, function (err) {
            if (err) {
                next(err)
            } else {
                logger.debug(`"${filepath}" was sent`);
            }
        })
    }

    function result(code, data, msg) {
        return JSON.stringify({
            code: code,
            data: data,
            msg: msg
        });
    }
}